﻿#include "StdAfx.h"
#include "Globals.h"
#include "Draw.h"
#include <limits>


const
TiledTexture*	FlyingButton::tex	= NULL;
float				Movable::scale		= 1.0f;
float				Movable::sx			= 1.0f;
float				Movable::sy			= 1.0f;

const
double			Animated::IDLE		= std::numeric_limits<double>::lowest();

/*
#undef UINT64_C
#include <boost\math\special_functions\ellint_2.hpp>

//-----------------------------------------------------------------------------
float arc_length_sin(float phi)
{
	#define N 1024
	static float table[N+1];

	static bool initialized = false;

	static const float	f = float(N/(2.0*PI)),
								g = float((2.0*PI)/N);

//----
	if(!initialized)
	{
		initialized = true;

		for(int i = 0; i <= N; i++)
		{
			float phi = float(2.0*PI*i/N);
			table[i] = sqrt(2.0f)*boost::math::ellint_2<float>(sqrt(0.5f),phi);
		}
	}

	int	i = int(f * phi),
			n = i / N;

	i %= N;

	float remWeight = f * (phi - n*2.0*PI - g*i);

	return n * table[N] + (1.0f-remWeight)*table[i] + remWeight*table[i+1];
}
*/

//-----------------------------------------------------------------------------
void PixelColor(float r, float g, float b, float a)
{
	glPixelTransferf(GL_RED_BIAS,		r-1.0f);
	glPixelTransferf(GL_GREEN_BIAS,	g-1.0f);
	glPixelTransferf(GL_BLUE_BIAS,	b-1.0f);
	glPixelTransferf(GL_ALPHA_BIAS,	a-1.0f);
}

//-----------------------------------------------------------------------------
void PixelColorReset()
{
	glPixelTransferf(GL_RED_BIAS,		0.0f);
	glPixelTransferf(GL_GREEN_BIAS,	0.0f);
	glPixelTransferf(GL_BLUE_BIAS,	0.0f);
	glPixelTransferf(GL_ALPHA_BIAS,	0.0f);
}


//-----------------------------------------------------------------------------
void FontColor(float r, float g, float b, float a)
{
#ifdef USE_FTGL
			PixelColor(r,g,b,a);
#else
			glColor4f (r,g,b,a);
#endif
}

//-----------------------------------------------------------------------------
void DrawString(const std::wstring &str, float x, float y)
{
#ifdef USE_FTGL

	static FTGLPixmapFont font("font/meiryo.ttc");
	static bool init = true;
	if(init)
	{
		init = false;
		font.FaceSize(28);
		font.UseDisplayList(true);
	}
	RECT window;
	GetClientRect(PTT::wnd->getHWND(), &window);
	FTPoint p(x, y);
	p.Y(window.bottom - y - 28);
	font.Render(str.c_str(), -1, p);

#else

	PTT::FixedFont->drawString(str, x, y);

#endif
}

//-----------------------------------------------------------------------------
void DrawStars(int filled, int half, int total, float x, float y, bool rightAligned)
{
	std::wstring s(total, L'☆');
	int i;
	for(i = 0; i < filled; i++)
		s[i] = L'★';
	for(; i < filled+half; i++)
		s[i] = L'☆'+1;							// The unicode symbol with this code is actually '☇', only in our texture it is a "half star"

	PTT::Symbols->drawString(s, x, y, 1.0f, rightAligned ? align::right : align::left);
}


//-----------------------------------------------------------------------------
void DrawRect(int left, int top, int right, int bottom)
{
	glDisable(GL_TEXTURE_2D);
	glBegin(GL_TRIANGLE_STRIP);
		glVertex2i(left,  top);
		glVertex2i(right, top);
		glVertex2i(left,  bottom);
	 	glVertex2i(right, bottom);
	glEnd();
	glEnable(GL_TEXTURE_2D);
}


//-----------------------------------------------------------------------------
void FlyingButton::step(double time)
{
	double dt = time - now;
	now = time;
	t = now - t0;

	if(t >= 0 && t < 1.1*duration)
	{
		t /= duration;							// t is now between [0,1.1)

		if(pathPos.x == 1.0e9)				// initialize pathPos
		{
			pathPos.x = (float)s.x;
			pathPos.y = (float)s.y;
		}

		if(!hit)
		{
			float t_ = float(t);
			if(tFunction)
				t_ = tFunction->evaluate(t_);
			float	v_ = float(v.x),
					s_ = 1024.0f*(1.0f-t_);	// parameter s = distance on the straight line

			Point	perp	= path.dir.perp(),
					sNew	= path.end - path.dir * s_;

			float	phi1	= path.omega1 * s_,
					sin1	= path.alpha1 * sin(phi1);
			float	phi2	= path.omega2 * s_,
					cos2	= path.alpha2 * cos(phi2);

			if(path.omega2 > 0)	cos2 = cos2-path.alpha2;
			else						cos2 = path.alpha2-cos2;

			sNew += perp*sin1;

			perp = (pathPos - sNew).perp().normalize();

			if(pathPos != sNew)
				pathPos  = sNew;

			sNew += perp*cos2;

			Point change(float(sNew.x-s.x), float(sNew.y-s.y));

			perp = change;
			perp.x *= sx;
			perp.y *= sy;

			Point				sTrail	= sNew;
	//		if(t > 1.0)		sTrail	= trail[trailIndex-1];//*0.9f+sNew*0.1f;
			trailTexS[trailIndex]	= float((chanceTime?0.0025f:0.006f)*(sTrail-path.end).norm()+0.01f*time);
			trailPerp[trailIndex]	= perp.perp().normalize()*24.0f;
			trail		[trailIndex++]	= sTrail;

			s.x = sNew.x;
			s.y = sNew.y;
		}
	}
	else if(t >= duration)
	{
		t = IDLE;
//		s.x = P[0].x;
//		s.y = P[0].y;
	}

	tOld = t;
}

//-----------------------------------------------------------------------------
void FlyingButton::draw() const
{
	if(idle())
		return;


	float x = sx*float(s.x),
			y = sy*float(s.y),
			S = size*scale;

//----
//	fade out and get smaller
	float a = 1.0f;
	if(t > 1.0)									// t is between [0,1.1)
	{
		a -= 10.0f*float(t - 1.0);
		S *= a;
	}

// adjust position of the triangle button, as its texture is not centered.
	if(id==3)
		y -= 0.09f*S*tex->getHeight();

	glColor4f(1.0f, 1.0f, 1.0f, a);
	tex->draw(id, x, y, S, true);
}


//-----------------------------------------------------------------------------
void FlyingButton::drawTrail() const
{
	static const Texture trail1(L"graphics/trail1.png");
	static const Texture trail2(L"graphics/trail2.png");
	static const Color	colorTable[4] = {Color(255,165,182), Color(144,236,249), Color(255,198,255), Color(169,255,246)};
	double t = now - t0;
	if(t < 0)
		return;

// our trail fades out after 256 frames / 60 fps = 4.268 seconds
	float alpha = 1.0f;
	if(t > duration)
	{
//		if(t > duration + 8.54)				// 30 fps limit
		if(t > duration + 4.3)				// 60 fps limit
			return;
	}

	float x = sx*float(s.x),
			y = sy*float(s.y),
			S = size*scale;

//----
//	glPushMatrix();
//	glScalef(sx,sy,1.0f);
	Color c;	int A = 24, aStep = 1;

	if(chanceTime)
	{
		c = white;
		trail2.bind();
		alpha = sqr((256.0f-hit) / 256.0f);							// when hit, the trail will actually fade out faster than before
	}
	else
	{
		c = colorTable[id];
		aStep = 3;
		alpha = sqr(max(256.0f-8*hit, 0.0f) / 288.0f);
		trail1.bind();
	}
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);

	glBegin(GL_TRIANGLE_STRIP);
		int i, n = 0;
		for(i = trailIndex-1; i >= 0; i--, n++)					// newer data
		{
			c.A = BYTE(alpha*max(A-hit,0)+0.5f);
			c.glApply();
			Point	p		(sx*trail [i].x, sy*trail[i].y);
			Point	perp	(trailPerp[i] * scale);
			glTexCoord2f(trailTexS[i],0.0f);	glVertex2fv(p+perp);
			glTexCoord2f(trailTexS[i],1.0f);	glVertex2fv(p-perp);

			if(n < 8)	A += 28;
			else			A -= aStep;
		}

		for(i = (i+256)%256; i >= trailIndex; i--, n++)			// older data
		{
			c.A = BYTE(alpha*max(A-hit,0)+0.5f);
			c.glApply();
			Point	p		(sx*trail [i].x, sy*trail[i].y);
			Point	perp	(trailPerp[i] * scale);
			glTexCoord2f(trailTexS[i],0.0f);	glVertex2fv(p+perp);
			glTexCoord2f(trailTexS[i],1.0f);	glVertex2fv(p-perp);

			if(n < 8)	A += 28;
			else			A -= aStep;
		}
	glEnd();
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
//	glPopMatrix();

	if(hit)
		hit++;																// count # frames since hit
}

